package org.sdfc.query

import scala.collection.mutable.ArrayBuffer

import com.documentum.fc.client.IDfSession
import com.documentum.fc.common.DfException

import org.sdfc.model.attr.SingleAttribute
import org.sdfc.model.attr.SingleStringAttribute
import org.sdfc.model.dfc.collection.CollectionRows

/** TypedQuery prepared for its execution.
 *  <p>
 *  Provides useful extraction methods for the common use cases.
 */
class PreparedQuery (
  /** TypedQuery to be executed. */
  val query : TypedQuery,
  /** DFC session. */
  val session : IDfSession
) {
  
  /** Executes the query and collects the values of <code>attr</code> from all rows
   *  into an ArrayBuffer.
   */
  @throws(classOf[DfException])
  def extract[T](attr : SingleAttribute[T]) : ArrayBuffer[T] = {
    val attrGF = attr.genericForm
    for ( row <- query.rows(session) )
      yield attrGF.get(row)
  }
  
  /** Executes the query and reads the value of <code>attr</code> in the first row of results.<br/>
   *  Returns <code>Some(value)</code> if there was a first row, else <code>None</code>.
   */
  @throws(classOf[DfException])
  def extractFirst[T](attr : SingleAttribute[T]) : Option[T] = {
    val attrGF = attr.genericForm
    for ( row <- query.firstRow(session) )
      yield attrGF.get(row)
  }
  
  
  /** Executes the query and collects 2-tuples of the values of <code>attr1</code> and <code>attr2</code2>
   *  into an ArrayBuffer.
   */
  @throws(classOf[DfException])
  def extract[T, U](attr1 : SingleAttribute[T], attr2 : SingleAttribute[U]) : ArrayBuffer[(T, U)] = {
    val attrGF1 = attr1.genericForm
    val attrGF2 = attr2.genericForm
    for ( row <- query.rows(session) )
      yield ( attrGF1.get(row), attrGF2.get(row) )
  }
  
  /** Executes the query and reads the values of <code>attr1</code> and <code>attr2</code> in the first row of results.<br/>
   *  Returns <code>Some((value1, value2))</code> if there was a first row, else <code>None</code>.
   */
  @throws(classOf[DfException])
  def extractFirst[T, U](attr1 : SingleAttribute[T], attr2 : SingleAttribute[U]) : Option[(T, U)] = {
    val attrGF1 = attr1.genericForm
    val attrGF2 = attr2.genericForm
    for ( row <- query.firstRow(session) )
      yield ( attrGF1.get(row), attrGF2.get(row) )
  }
  
  
  /** Executes the query and collects Array[String] of the values of <code>attrs</code>
   *  into an ArrayBuffer.
   */
  @throws(classOf[DfException])
  def extract(attrs : Array[SingleStringAttribute]) : ArrayBuffer[Array[String]] =
    for ( row <- query.rows(session) )
      yield {
        for ( attr <- attrs )
          yield row.getString(attr)
      }
  
  /** Execute the query and reads a Array[String] of the values of <code>attrs</code> in the first row of results.<br/>
   *  Returns <code>Some(values)</code> if there was a first row, else <code>None</code>.
   */
  @throws(classOf[DfException])
  def extractFirst(attrs : Array[SingleStringAttribute]) : Option[Array[String]] =
    for ( row <- query.firstRow(session) )
      yield {
        for ( attr <- attrs )
          yield row.getString(attr)
      }
  
}
